import {defineComponent, onMounted, reactive} from 'vue';

import './theme-edit-panel.scss';
import {getConfiguration} from "./sass.utils";
import {deepcopy} from "@/utils/deepcopy";
import {$$dialog, DialogServiceEditType} from 'plain-ui/src/packages/dialog-service';
import {defer} from "@/utils/defer";
import {downloadText} from "@/docs/overview/theme/download";

enum EditType {
  color = 'color',
  number = 'number',
}

//所有影响主题的颜色变量
const EditConfig = [
  {
    title: 'Status',
    tip: '状态色',
    data: [
      {title: 'Primary', tip: '基础', key: 'colorPrimary', type: EditType.color},
      {title: 'Success', tip: '成功', key: 'colorSuccess', type: EditType.color},
      {title: 'Warn', tip: '警告', key: 'colorWarn', type: EditType.color},
      {title: 'Error', tip: '错误', key: 'colorError', type: EditType.color},
      {title: 'info', tip: '帮助', key: 'colorInfo', type: EditType.color}
    ]
  },
  {
    title: 'Color',
    tip: '其他颜色',
    data: [
      {title: 'Border', tip: '边框色', key: 'ibc', type: EditType.color},
      {title: 'Border(light)', tip: '边框色(轻)', key: 'ibl', type: EditType.color},
      {title: 'Text', tip: '文本色', key: 'itc', type: EditType.color},
      {title: 'Text(light)', tip: '文本色(轻)', key: 'itl', type: EditType.color},
      {title: 'Head', tip: '标题色', key: 'ihc', type: EditType.color},
      {title: 'Placeholder', tip: '占位符颜色', key: 'ipc', type: EditType.color},
      {title: 'Icon', tip: '图标色', key: 'icc', type: EditType.color}
    ]
  },
  {
    title: 'Disabled',
    tip: '禁用色',
    data: [
      {title: 'Disabled', tip: '禁用', key: 'disabled', type: EditType.color},
      {title: 'Disabled(light)', tip: '禁用(轻)', key: 'disabledLight', type: EditType.color},
      {title: 'Disabled(deep)', tip: '禁用(深)', key: 'disabledDeep', type: EditType.color},
      {title: 'Disabled(text)', tip: '禁用字体', key: 'disabledText', type: EditType.color}
    ]
  },
  {
    title: 'Size',
    tip: '尺寸',
    data: [
      {title: 'Large', tip: '大尺寸', key: 'sizeLarge', type: EditType.number},
      {title: 'Normal(default)', tip: '中尺寸', key: 'sizeNormal', type: EditType.number},
      {title: 'Mini', tip: '小尺寸', key: 'sizeMini', type: EditType.number},
      {title: 'Fillet', tip: '圆角大小', key: 'shapeFillet', type: EditType.number}
    ]
  }
]

type PromiseType<T> = T extends Promise<infer R> ? R : never
export const ThemeEditor = (() => {
  const state = reactive({
    data: {} as Record<string, string>,
    configuration: null as null | PromiseType<ReturnType<typeof getConfiguration>>
  });
  const utils = {
    init: async () => {
      state.configuration = await getConfiguration();
      state.data =  ThemeCache.data.themeData || deepcopy(state.configuration.defaultEditData);
    },
    getUserThemeName: () => {
      const dfd = defer<string>()

      /*$$dialog({
        title: '请输入主题名称(为空则主题应用在html下)',
        editValue: '',
        editType: DialogServiceEditType.input,
        confirmButton: true,
        cancelButton: true,
        onConfirm: async (themeName) => dfd.resolve(themeName || '')
      });*/
      //todo ↑ 报找不到对应的sassmixin ... emmm

      dfd.resolve('');

      return dfd.promise;
    }
  };
  const methods = {
    apply: () => {
      console.log('apply--- --- ---');
      useTheme(state.data, state.configuration!.generateCssFile)
    },
    reset: async () => {
      console.log('重置');
      state.data = deepcopy(state.configuration!.defaultEditData)
      await methods.apply()
    },
    downloadVariables: async()=>{
      console.log('下载主题变量');
      const themeName = await utils.getUserThemeName();
      const variables = await state.configuration!.generateVariables(state.data, themeName)
      await downloadText(variables, `${!!themeName ? `theme-${themeName}` : "default"}.scss`)
    },
    downloadCssFile: async()=>{
      console.log('下载主题样式');
      const themeName = await utils.getUserThemeName()
      const cssText = await state.configuration!.generateCssFile(state.data, themeName)
      await downloadText(cssText, `${!!themeName ? `theme-${themeName}` : "default"}.css`)
    },
    downloadVariablesJson: async ()=>{
      console.log('下载JSON数据')
      /*$$dialog({
        title: '主题变量json数据',
        editType: DialogServiceEditType.textarea,
        editValue: JSON.stringify(state.data),
        editReadonly: true,
      })*/
    }
  };

  return {
    state,
    utils,
    methods
  }
})();

const ThemeCache = (() => {
  const THEME_STORAGE_KEY
    = '@@THEME_STORAGE';

  let data: {
    themeData?: Record<string, string>,
    code?: string;
  } = {};

  const cache = window.localStorage.getItem(THEME_STORAGE_KEY);
  if(!!cache){
    data = JSON.parse(cache) as any;
  }

  return {
    data,
    storage: (themeData: Record<string, string>, code: string) => {
      window.localStorage.setItem(THEME_STORAGE_KEY, JSON.stringify({themeData, code}));
    }
  }
})();

/**
 * 第一次调用会往html里插入一个 <style id='custom-theme'>
 * 后面如果还被调用, 只会改变style标签的innerHTML
 */
const useTheme = (() => {
  let el: HTMLElement | null = null
  const useCode = (code:string)=>{
    if(!code) return;
    console.log('code:', code);
    if(!el){
      el = document.createElement('style');
      el.setAttribute('id', 'custom-theme');
      document.body.appendChild(el);
    }
    el.innerHTML = code;
  }

  // 之前如果配置过, 就使用之前存在本地的缓存 (这里是自执行闭包
  if(!!ThemeCache.data.code) useCode(ThemeCache.data.code);

  const fn = async (themeData: Record<string, string>, themeCompiler: (themeData: Record<string, string>, themeName: string) => Promise<string>) => {
    console.log('useTheme --- --- ---');
    const code = await themeCompiler(themeData, '');
    useCode(code);
    ThemeCache.storage(themeData, code);
  };
  return fn;
})();

export const ThemeEditPanel = defineComponent({
  setup(){
    const {state, methods, utils} = ThemeEditor

    onMounted(utils.init);

    return () => (
      <div class='theme-edit-panel'>
        <div class='theme-edit-panel__head'>
          <div onClick={methods.apply}>
            <pl-icon icon='el-icon-debug-s'/>
            <span>应用</span>
          </div>
          <div onClick={methods.reset}>
            <pl-icon icon='el-icon-refresh'/>
            <span>重置</span>
          </div>
          <pl-dropdown width='140' placement='bottom-end'>
            {
              {
                default: ()=>(
                  <div>
                    <pl-icon icon='el-icon-download'/>
                    <span>下载</span>
                  </div>
                ),
                popper: ()=>(
                  <pl-dropdown-menu>
                    <pl-dropdown-option label='下载主题变量' icon='el-icon-debug-s' onClick={methods.downloadVariables}/>
                    <pl-dropdown-option label='下载主题样式' icon='el-icon-document' onClick={methods.downloadCssFile}/>
                    <pl-dropdown-option labe='下载JSON数据' icon='el-icon-edit-outline' onClick={methods.downloadVariablesJson}/>
                  </pl-dropdown-menu>
                )
              }
            }
          </pl-dropdown>
        </div>
        <div class='theme-edit-panel__body'>
          <div class="theme-edit-panel__body__content">
            {
              EditConfig.map(group=>(
                <div class='theme-edit-panel__body__content__group' key={group.title}>
                  <div class="theme-edit-panel__body__content__group__title">
                    <span>{group.title}</span>
                    <span>{group.tip}</span>
                  </div>
                  {
                    group.data.map((item,index)=>(
                      <div class='theme-edit-panel__body__content__group__item'>
                        <div class='theme-edit-panel__body__content__group__item__title'>
                          <span>{item.title}</span>
                          <span>{item.tip}</span>
                        </div>
                        <div>
                          {
                            item.type === EditType.color? (
                              <pl-color-picker v-model={state.data[item.key]}/>
                            ):(
                              <pl-number v-model={state.data[item.key]} />
                            )
                          }
                        </div>
                      </div>
                    ))
                  }
                </div>
              ))
            }
          </div>
        </div>
      </div>
    )
  }
});

